package de.akabahn.ebd.comm.socket;

import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;

import de.akabahn.ebd.comm.Util;

/**
 * Socket bridge that is used to connect to the a server. According to the
 * Android application design guidelines this is done in a separate thread,
 * because Android denies network connection calls in the main thread per
 * default (this implementation ensures that the DBD connection interface can
 * be used within an Andriod application).
 * 
 * @author Peter Eimann
 * @since 0.1
 * @version 0.1
 */
public class SocketBridge implements Runnable {
	private boolean stopped;
	private String server;
	private int port;
	private Socket socket;
	private CountDownLatch connectedLatch;
	private Exception threadException;

	/**
	 * Configure the socket bridge with the passed parameters.
	 * 
	 * @param socket
	 *            The socket instance used to connect and disconnect from
	 *            the server
	 * @param server
	 *            The name or ip-address of the server
	 * @param port
	 *            The port to connect to
	 * @param connectedLatch
	 *            The latch that is decreased after the connection has been
	 *            established
	 */
	public SocketBridge(Socket socket, String server, int port, CountDownLatch connectedLatch) {
		this.socket = socket;
		this.server = server;
		this.port = port;
		this.connectedLatch = connectedLatch;
	}

	/**
	 * Set the <code>isStopped</code> flag to true to prepare the current thread
	 * to stop
	 */
	public void prepareToStop() {
		stopped = true;
	}

	/**
	 * Return the exception that might have been caught in the thread.
	 * 
	 * @return the threadException (may be <code>null</code>)
	 */
	public Exception getThreadException() {
		return threadException;
	}

	/**
	 * Connect to the server and then loop until this thread should be
	 * stopped (by calling the <code>prepareToStop()</code> method. Before the
	 * thread stops, the connection to the server is closed. The
	 * <code>connectedLatch</code> that had been passed in the constructor is
	 * decreased to signal the calling thread the successful connection.
	 * 
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		boolean connected = false;

		try {
			socket.connect(new InetSocketAddress(server, port), 30000);
			connected = true;
		} catch (Exception e) {
			connectedLatch.countDown();
			threadException = e;
		}

		while (!stopped && (threadException == null)) {
			connectedLatch.countDown();
			try {
				Util.sleep(500);
			} catch (Exception e) {
				threadException = e;
			}
		}

		if (connected) {
			try {
				socket.close();
			} catch (Exception e) {
				threadException = e;
			}
		}
	}
}
